package api

import (
	"fm/auth"
	"fm/database"
	"fm/model"
	"fm/utils"
	"github.com/gin-gonic/gin"
	"log"
	"math/rand"
	"net/http"
	"strconv"
	"strings"
	"time"
)

type UserCredentials struct {
	UserName string `json:"user_name"`
	Password string `json:"password"`
	Mobile   string `json:"mobile"`
	Email    string `json:"email"`
	NickName string `json:"nick_name"`
	WeiXin   string `json:"weixin"`
	QQ       string `json:"qq"`
}

type AccountCredentials struct {
	Name   string `json:"name"`
	Org    int    `json:"org"`
	Person int    `json:"person"`
}

type LogCredentials struct {
	UserId     int     `json:"user_id"`
	AccountId  int     `json:"account_id"`
	Amount     float32 `json:"amount"`
	Summary    string  `json:"summary"`
	Category   string  `json:"category"`
	CategoryId int     `json:"category_id"`
	OrgId      int     `json:"org_id"`
	PersonId   int     `json:"person_id"`
}

/**********************************************
  user table处理API
*********************************************/

//RegisterHandler 注册用户处理API
func RegisterHandler(c *gin.Context) {
	//1、生成随机的用户ID
	rand.Seed(time.Now().UnixNano())
	id := rand.Intn(database.MAXUSERID)

	log.Println("id:", id)
	//2、获取用户名，如果没有则用"user_"+id做为用户名

	cred := UserCredentials{}

	if err := c.ShouldBind(&cred); err != nil {
		c.Abort()
	}
	//3、判断用户名、密码、手机号、EMAIL是否规范
	user := model.User{}
	user.UserId = id
	user.UserName = cred.UserName
	if err := user.SetPassword(cred.Password); err != nil {
		log.Println("error in user.SetPassword")
		c.Abort()
	}
	if utils.VerifyEmailFormat(cred.Email) {
		user.Email = cred.Email
	} else {
		user.Email = ""
	}
	if utils.VerifyMobileFormat(cred.Mobile) {
		user.Mobile = cred.Mobile
	} else {
		user.Mobile = ""
	}

	user.NickName = cred.NickName
	user.QQ = cred.QQ
	user.Weixin = cred.WeiXin
	user.CreatedAt = time.Now().Unix()

	if len(user.UserName) == 0 {
		user.UserName = "user_" + strconv.Itoa(id)
	}

	//4、将用户数据插入数据库
	err := database.AddUser(user)
	if err != nil {
		c.String(http.StatusBadRequest, "Failed to Add User!")
		c.Abort()
		return
	}
	//5、新增用户成功，向客户端返回信息
	c.JSON(http.StatusOK, gin.H{
		"id":         user.UserId,
		"username":   user.UserName,
		"mobile":     user.Mobile,
		"email":      user.Email,
		"created_at": time.Unix(user.CreatedAt, 0).Format("2006-01-02 15:04:05"),
		"status":     "Success Add User",
	})

}

//LoginHandler 用户登录API处理函数
func LoginHandler(c *gin.Context) {

	//获取请求中的登录信息
	cred := UserCredentials{}
	if err := c.ShouldBind(&cred); err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{
			"status": false,
			"cause":  "None user",
		})
		c.Abort()
		return
	}

	//根据请求中的用户名，查询数据库
	userDb, ok := database.QueryUserByName(cred.UserName)
	if !ok {
		log.Println("没有查到用户")
		c.JSON(http.StatusUnauthorized, gin.H{
			"status": false,
			"cause":  "None user",
		})
		c.Abort()
		return
	}

	//验证密码
	if err := userDb.CheckPassword(cred.Password); err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{
			"status": false,
			"cause":  "password wrong!",
		})
		c.Abort()
		log.Println("Login failed!")

	} else {
		//验证通过，生成令牌给客户端
		log.Println("Login success")
		token := auth.IssueToken(userDb.UserId, userDb.UserName)
		c.JSON(http.StatusOK, gin.H{
			"status":    true,
			"token":     token,
			"user_name": userDb.UserName,
			"user_id":   userDb.UserId,
		})
	}

}

//DelUserHandler 删除用户处理API
func DelUserHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("Delete User:", userId)
	err := database.DelUser(userId)
	if err != nil {
		c.JSON(http.StatusNotModified, gin.H{
			"status":  false,
			"message": "Delete user failed!",
		})
		c.Abort()
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Delete user success!",
	})

}

//UpdateUserHandler 更新用户信息处理API
func UpdateUserHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	cred := UserCredentials{}
	if err := c.ShouldBind(&cred); err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{
			"status": false,
			"cause":  "user info error",
		})
		c.Abort()
		return
	}
	var res map[string]string
	res = make(map[string]string)
	if len(cred.Password) >= 8 && len(cred.Password) <= 128 {
		hash, err := model.HashPassword(cred.Password)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"status": false,
				"cause":  "hash password error!",
			})
			c.Abort()
			return
		}
		if database.ChangeUserPassword(userId, hash) {
			log.Println("UpdateUserHandler():update user password successful.")
			res["password"] = "password update success."
		} else {
			log.Println("UpdateUserHandler():update user password failed!")
			res["password"] = "password update failed."
		}
	} else {
		if len(cred.Password) == 0 {
			res["password"] = "No password"
		} else {
			res["password"] = "wrong password."
		}
	}
	if utils.VerifyEmailFormat(cred.Email) {
		if database.ChangeUserEmail(userId, cred.Email) {
			log.Println("UpdateUserHandler():update user email successful.")
			res["email"] = "email update success."
		} else {
			log.Println("UpdateUserHandler():update user email failed!")
			res["email"] = "email update failed."
		}
	} else {
		if len(cred.Email) == 0 {
			res["email"] = "No email"
		} else {
			res["email"] = "wrong email."
		}
	}
	if utils.VerifyMobileFormat(cred.Mobile) {
		if database.ChangeUserMobile(userId, cred.Mobile) {
			log.Println("UpdateUserHandler():update user mobile successful.")
			res["mobile"] = "mobile update success."
		} else {
			log.Println("UpdateUserHandler():update user mobile failed!")
			res["mobile"] = "mobile update failed."
		}
	} else {
		if len(cred.Mobile) == 0 {
			res["mobile"] = "No mobile"
		} else {
			res["mobile"] = "wrong mobile."
		}
	}
	if len(cred.NickName) > 0 && len(cred.NickName) < 255 {
		if database.ChangeUserNickName(userId, cred.NickName) {
			log.Println("UpdateUserHandler():update user nick name successful.")
			res["nick_name"] = "Nick name update success."
		} else {
			log.Println("UpdateUserHandler():update user nick name failed!")
			res["nick_name"] = "Nick name update failed."
		}
	} else {
		if len(cred.NickName) == 0 {
			res["nick_name"] = "No nick name"
		} else {
			res["nick_name"] = "wrong nick name."
		}
	}
	if len(cred.WeiXin) > 0 && len(cred.WeiXin) < 255 {
		if database.ChangeUserWeixin(userId, cred.WeiXin) {
			log.Println("UpdateUserHandler():update user weixin successful.")
			res["Weixin"] = "Weixin update success."
		} else {
			log.Println("UpdateUserHandler():update user weixin failed!")
			res["Weixin"] = "Weixin update failed."
		}
	} else {
		if len(cred.WeiXin) == 0 {
			res["Weixin"] = "No Weixin"
		} else {
			res["Weixin"] = "wrong Weixin."
		}
	}
	if len(cred.QQ) > 0 && len(cred.WeiXin) < 15 {
		if database.ChangeUserQQ(userId, cred.QQ) {
			log.Println("UpdateUserHandler():update user QQ successful.")
			res["QQ"] = "QQ update success."
		} else {
			log.Println("UpdateUserHandler():update user QQ failed!")
			res["QQ"] = "QQ update failed."
		}
	} else {
		if len(cred.QQ) == 0 {
			res["QQ"] = "No QQ"
		} else {
			res["QQ"] = "wrong QQ."
		}

	}

	c.JSON(http.StatusOK, gin.H{
		"status": true,
		"res":    res,
	})
}

//QueryUserHandler 查询用户信息处理API
func QueryUserHandler(c *gin.Context) {

	//获得用户ID
	//ID := c.MustGet("id").(int)
	Name := c.MustGet("name").(string)
	//log.Println("user name= ", Name)
	userDb, ok := database.QueryUserByName(Name)
	if !ok {
		log.Println("查询用户失败，用户Name=", Name)
		c.JSON(http.StatusBadRequest, gin.H{
			"status": false,
			"cause":  "query user failed!",
		})
		c.Abort()
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"user_id":   userDb.UserId,
		"user_name": userDb.UserName,
		"nick_name": userDb.NickName,
		"mobile":    userDb.Mobile,
		"email":     userDb.Email,
	})
}

/********************************************
   accounts table 处理API
*******************************************/

//NewAccountHandler 新增账户处理API
func NewAccountHandler(c *gin.Context) {

	cred := AccountCredentials{}
	if err := c.ShouldBind(&cred); err != nil {
		c.Abort()
	}
	log.Println(cred.Name)
	id := c.MustGet("id").(int)

	err := database.AddAccount(id, cred.Name, cred.Org, cred.Person, 0)
	if err != nil {
		c.Abort()
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"token":   true,
		"user_id": id,
	})
}

//DelAccountHandler 删除账户处理API
func DelAccountHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	idString := c.Query("account_id")
	accountId, err := strconv.Atoi(idString)
	if err != nil {
		log.Println("Account id is wrong!", err)
		c.Abort()
	}
	err = database.DelAccount(userId, accountId)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"status": false,
			"cause":  "Del Account failed",
		})
	}
	c.JSON(http.StatusOK, gin.H{
		"status": true,
		"cause":  "Del account success!",
	})
}

//QueryAccountsHandler 查询用户所有账户API
func QueryAccountsHandler(c *gin.Context) {
	//获取账户ID，根据ID去查询账户信息
	userId := c.MustGet("id").(int)

	//查询账户信息

	accounts, err := database.QueryAccounts(userId)
	if err != nil {
		log.Println("Query accounts failed! error:", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"status": false,
			"cause":  "Query account failed!",
		})
		c.Abort()
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"status":   true,
		"accounts": accounts,
	})
}

/********************************************
   accounts_log table处理API
*******************************************/

//NewAccountsLogHandler 新增记账记录
func NewAccountsLogHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	cred := LogCredentials{}
	err := c.ShouldBind(&cred)
	if err != nil {
		log.Println("NewAccountsLogHandler(): error in bind logCredentials. ", err)
		c.JSON(http.StatusBadRequest, gin.H{
			"status": false,
			"cause":  "credentials wrong!",
		})
		c.Abort()
		return
	}
	accountsLog := model.AccountsLog{}
	accountsLog.UserId = userId
	accountsLog.AccountId = cred.AccountId
	accountsLog.Amount = cred.Amount
	accountsLog.Summary = cred.Summary
	accountsLog.Category = cred.Category
	accountsLog.CategoryId = cred.CategoryId
	accountsLog.OrgId = cred.OrgId
	accountsLog.PersonId = cred.PersonId
	err = database.AddAccountsLog(accountsLog)
	if err != nil {
		log.Println("NewAccountsLogHandler():error insert a log.", err)
		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"user_id": userId,
		})
		c.Abort()
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":      true,
		"user_id":     userId,
		"amount":      accountsLog.Amount,
		"summary":     accountsLog.Summary,
		"category":    accountsLog.Category,
		"category_id": accountsLog.CategoryId,
		"org_id":      accountsLog.OrgId,
		"person_id":   accountsLog.PersonId,
	})
}

//DelAccountsLogHandler 删除一条记账记录
func DelAccountsLogHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	accountId, _ := strconv.Atoi(c.Query("account_id"))
	logId, _ := strconv.Atoi(c.Query("log_id"))
	err := database.DelAccountsLog(userId, accountId, logId)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"status": false,
			"cause":  "del accounts log failed!",
		})
		c.Abort()
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"status": true,
		"cause":  "del accounts log success!",
	})
}

//QueryAccountsLogHandler 查询账户下的所有记账条目
func QueryAccountsLogHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	accountId, _ := strconv.Atoi(c.Query("account_id"))
	if accountId == 0 {
		c.JSON(http.StatusInternalServerError, gin.H{
			"status": false,
			"cause":  "account_id not detected.",
		})
		c.Abort()
		return
	}
	rows, err := database.QueryAccountsLog(userId, accountId)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"status": false,
			"cause":  "query accounts log failed!",
		})
		c.Abort()
		return
	}

	var resp []interface{}
	for _, row := range rows {
		//log.Println(i,row)
		resp = append(resp, row)
	}
	c.JSON(http.StatusOK, gin.H{
		"status": true,
		"cause":  "query accounts log success!",
		"rows":   resp,
	})
}

/*****************************************
	org table 处理API
 ****************************************/

//NewOrgHandler 新增一个机构
func NewOrgHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	name := c.Query("name")

	db := database.GetDB()
	_, err := db.Exec("insert into org set user_id =?,name = ?;", userId, name)
	if err != nil {
		log.Println("NewOrgHandler():error in insert org into table.error:", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"status": false,
			"cause":  "insert into table error!",
		})
		c.Abort()
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"user_id": userId,
		"name":    name,
	})

}

//DelOrgHandler 删除一个机构
func DelOrgHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	//log.Println("user id :", userId)
	idString := c.Query("org_id")
	id, _ := strconv.Atoi(idString)
	db := database.GetDB()
	_, err := db.Exec("delete from org where org_id=? and user_id=?", id, userId)
	if err != nil {
		log.Println("NewOrgHandler():error in delete org from table.error:", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"status": false,
			"cause":  "delete org from  table error!",
		})
		c.Abort()
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"desc":    "delete org success",
		"user_id": userId,
		"org_id":  id,
	})
}

//QueryOrgHandler 查询所有机构
func QueryOrgHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("user id :", userId)
}

/******************************************
	person table 处理API
 ****************************************/

//NewPersonHandler 新增一个人员
func NewPersonHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("user id :", userId)
}

//DelPersonHandler 删除一个人员
func DelPersonHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("user id :", userId)
}

//QueryPersonHandler 查询所有人员
func QueryPersonHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("user id :", userId)
}

/*************************************************
	income table 处理API
 ************************************************/

//NewIncomeHandler 新增一个人员
func NewIncomeHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("user id :", userId)
}

//DelIncomeHandler 删除一个人员
func DelIncomeHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("user id :", userId)
}

//QueryIncomeHandler 查询所有人员
func QueryIncomeHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("user id :", userId)
}

/*************************************************
	expense table 处理API
 ************************************************/

//NewExpenseHandler 新增一个人员
func NewExpenseHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("user id :", userId)
}

//DelExpenseHandler 删除一个人员
func DelExpenseHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("user id :", userId)
}

//QueryExpenseHandler 查询所有人员
func QueryExpenseHandler(c *gin.Context) {
	userId := c.MustGet("id").(int)
	log.Println("user id :", userId)
}

//NeedToken 检查请求中是否带有令牌。令牌约定放在请求头中的Authorization Bearer中。
func NeedToken(c *gin.Context) {

	authString := c.Request.Header.Get("Authorization")

	kv := strings.Split(authString, " ")
	if len(kv) != 2 || kv[0] != "Bearer" {
		log.Println("NeedToken():token string not detected!")
		c.JSON(http.StatusUnauthorized, gin.H{
			"status": false,
			"cause":  "none token string detected!",
		})
		c.Abort()
		return
	}

	//得到令牌字串
	tokenString := kv[1]

	if tokenString == "" {
		log.Println("NeedToken():token string not detected!")
		c.JSON(http.StatusUnauthorized, gin.H{
			"status": false,
			"cause":  "none token string detected!",
		})
		c.Abort()
	} else {
		//验证令牌是否正确是否过期
		id, name, err := auth.ParseToken(tokenString)
		if err != nil {
			log.Println("NeedToken():token wrong!")
			c.JSON(http.StatusUnauthorized, gin.H{
				"status": false,
				"cause":  "token wrong!",
			})
			c.Abort()
		}
		//令牌正确，写入id和name,让下一个API处理
		c.Set("id", id)
		c.Set("name", name)
		c.Next()
	}
}
